package com.nervenets.general.web;

import com.nervenets.general.Global;
import com.nervenets.general.config.ApplicationProperties;
import com.nervenets.general.entity.ResponseResult;
import com.nervenets.general.exception.LogicException;
import com.nervenets.general.exception.TokenIllegalException;
import com.nervenets.general.jwt.aspect.JwtSecurity;
import com.nervenets.general.jwt.util.JwtUtils;
import com.nervenets.general.utils.FileUploadUtil;
import com.nervenets.general.utils.FileUtil;
import com.nervenets.general.utils.MimeTypeUtil;
import com.nervenets.general.utils.StringUtils;
import com.nervenets.general.web.vo.FileUploadProgress;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.boot.autoconfigure.web.servlet.MultipartProperties;
import org.springframework.context.annotation.Profile;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;

import static com.nervenets.general.Global.TokenIllegalType.MISS;
import static com.nervenets.general.Global.TokenIllegalType.VERIFY;
import static com.nervenets.general.i18n.I18nTranslator.translate;

/**
 * 2020/7/7 15:24 created by Joe
 **/
@Profile({"files"})
@Slf4j
@Api(tags = "文件类接口")
@RestController
@RequestMapping("/files")
public class FilesController extends BaseController {
    @Resource
    private ApplicationProperties applicationProperties;
    @Resource
    private MultipartProperties multipartProperties;

    /**
     * 通用上传
     *
     * @param file
     * @param request
     * @return
     * @throws IOException
     */
    @ApiOperation(value = "文件上传")
    @PostMapping("/upload")
    public ResponseEntity<ResponseResult<String>> upload(MultipartFile file, HttpServletRequest request) throws IOException {
        FileUploadUtil.DEFAULT_MAX_SIZE = multipartProperties.getMaxFileSize().toBytes();
        String uploadDir = applicationProperties.getStaticFileDirectory("upload");
        // 上传并返回新文件名称
        String[] extensions = applicationProperties.getDefaultAllowedExtensions();
        String fileName = FileUploadUtil.upload(uploadDir, file, extensions);
        return successMessage(fileName);
    }

    @ApiOperation(value = "文件上传进度")
    @GetMapping("/upload/progress")
    public ResponseEntity<ResponseResult<FileUploadProgress>> uploadProgress(HttpServletRequest request) {
        return successMessage((FileUploadProgress) request.getSession().getAttribute(Global.Constants.FILE_UPLOAD_PROGRESS_KEY));
    }

    /**
     * 通用下载请求
     *
     * @param fileName 文件名称
     * @param delete   是否删除
     */
    @ApiOperation(value = "文件下载")
    @GetMapping("/download")
    @JwtSecurity(required = false)
    public void download(String fileName, String name, Boolean delete, String token, HttpServletResponse response, HttpServletRequest request) throws IOException {
        if (StringUtils.isBlank(token)) throw new TokenIllegalException("I need a token", MISS);
        if (JwtUtils.verify(token, JwtUtils.license(request, applicationProperties.isTokenValidateDevice(), applicationProperties.isTokenValidateIp()))) {
            throw new TokenIllegalException(translate("application.login.expired") + "-verify", VERIFY);
        }

        if (StringUtils.isBlank(fileName)) throw new LogicException("文件名无效");
        String filePath = applicationProperties.getStaticFileDirectory(fileName);
        File file = new File(filePath);
        if (!file.exists()) throw new LogicException("文件不存在");

        String ext = FilenameUtils.getExtension(filePath);

        response.setCharacterEncoding("utf-8");
        response.setContentType("application/force-download");
        response.setHeader("Content-Length", String.valueOf(file.length()));
        response.setHeader("Content-Disposition",
                "attachment;fileName=" + FileUtil.setFileDownloadHeader(request, StringUtils.isBlank(name) ? fileName : name + "." + ext));
        FileUtil.writeBytes(filePath, response.getOutputStream());
        if (null != delete && delete) {
            FileUtil.deleteFile(filePath);
        }
    }

    @ApiOperation(value = "文件流")
    @GetMapping("/stream")
    public void stream(String fileName, HttpServletResponse response, HttpServletRequest request) throws Exception {
        if (StringUtils.isBlank(applicationProperties.getBaseStaticDomain()) || !applicationProperties.isUseBaseStaticDomain()) {
            if (StringUtils.isBlank(fileName)) throw new LogicException("文件名无效");
            String filePath = applicationProperties.getStaticFileDirectory(fileName);
            File file = new File(filePath);
            if (!file.exists()) throw new LogicException("文件不存在");

            response.setHeader("Accept-Ranges", "bytes");
            response.setHeader("Content-Length", String.valueOf(file.length()));
            response.setContentType(MimeTypeUtil.getMimeType(FilenameUtils.getExtension(filePath)));
            FileUtil.writeBytes(filePath, response.getOutputStream());
        } else {
            response.sendRedirect(applicationProperties.getBaseStaticDomain() + fileName);
        }
    }
}
